unit cfpdprconvert;

interface

type
  PDirectoryOptions = ^TDirectoryOptions;
  TDirectoryOptions = record
    UnitDir, IncludeDir, LibraryDir: string;
  end;

// Expected input format: pathname1;pathname2;pathname3
function ConvertFilepathsForFPC(const Prefix: string; const Paths: string): string;

// Expected input format: -X"pathname1;pathname2;pathname3" (where X can be any character)
function ConvertFilepathsForFPCFromCfg(const Prefix: string; Paths: string): string;

// Creates a string ready to be fed to FPC, filename can be .dpr or .cfg
function ReadAndConvertProjectCfg(Filename: string): string;

// Takes a TDirectoryOptions where each entry is in the input format pathname1;pathname2;pathname3
// and creates a string ready to be fed to FPC
function DirectoryOptionsToString(const Options: TDirectoryOptions): string;

implementation

uses
  cfcompileroptions,
  SysUtils, Classes;

function ConvertFilepathsForFPC(const Prefix: string; const Paths: string): string;
var
  sl: TStringList;
  s: string;
  i: Integer;
begin
  result := '';

  // Break up the path parameters seperated by ";"
  sl := TStringList.Create;
  try
    // We can not use TStringList.DelimitedText as this will
    // also break on space characters. However, in .cfg files spaces
    // are not quoted. This works:
    ExtractStrings([';'], [], PChar(Paths), sl);

    for i := 0 to sl.Count - 1 do
    begin
      s := trim(sl[i]);
      // Add each path parameter using the prefix. If there is a space
      // in this path, we have to quote it. Delphi 7 does not provide
      // any quoting.
      if pos(' ', s) > 0 then
        result := result + Prefix + '"' + s + '" ' // Not pre-quoted
      else
        result := result + Prefix + s + ' ';
    end;
  finally
    sl.Free;
  end;
end;

function ConvertFilepathsForFPCFromCfg(const Prefix: string; Paths: string): string;
var
  UnquotedPaths: string;
  Unused: PAnsiChar;
begin
  // First remove option name, eg "-U"
  Delete(Paths, 1, 2);
  // Remove outer quotes
  if pos('"', Paths) = 1 then
  begin
    Unused := PAnsiChar(Paths);
    UnquotedPaths := AnsiExtractQuotedStr(Unused, '"');
  end;
  result := ConvertFilepathsForFPC(Prefix, UnquotedPaths);
end;

function ReadAndConvertProjectCfg(Filename: string): string;
var
  sl: TStringList;
  s: string;
  i: Integer;
begin
  result := '';

  FileName := ChangeFileExt(FileName, '.cfg');

  if not FileExists(FileName) then exit;

  sl := TStringList.Create;
  try
    sl.LoadFromFile(Filename);
    for i := 0 to sl.Count - 1 do
    begin
      s := sl[i];

      if pos('-D', s)=1 then
      begin
        // conditional defines
        delete(s, 1, 2);
        while pos(';',s)>0 do
        begin
          result := result + '-d'+copy(s, 1, pos(';', s)-1)+' ';
          delete(s, 1, pos(';', s));
        end;
        if trim(s)<>'' then
          result := result + '-d'+s+' ';
      end else
      if pos('-U',s)=1 then
      begin
        // unit directory
        result := result + ConvertFilepathsForFPCFromCfg('-Fu', s);
      end else
      if pos('-O',s)=1 then
      begin
        // object directories
        result := result + ConvertFilepathsForFPCFromCfg('-Fo', s);
      end else
      if pos('-I',s)=1 then
      begin
        // include directories
        result := result + ConvertFilepathsForFPCFromCfg('-Fi', s);
      end;
    end;
  finally
    sl.Free;
  end;
end;

function DirectoryOptionsToString(const Options: TDirectoryOptions): string;
begin
  result := ConvertFilepathsForFPC('-Fu', Options.UnitDir) + ' ' +
            ConvertFilepathsForFPC('-Fi', Options.IncludeDir) + ' ' +
            ConvertFilepathsForFPC('-Fl', Options.LibraryDir);
end;

end.
